import Vue from 'vue'
import vuex from 'vuex'

let Store: any;

/**初始化VUEX */
export function store(module: any) {
    Vue.use(vuex)
    Store = new vuex.Store({
        state: {},
        modules: module
    })
    return Store
}

/**
 * 执行 vuex的Action
 * @param name 文件类名称可小写 
 * @param method 方法名称可小写，去掉方法前的A_,例A_USER填入[USER|user|User],
 * A_USER_NAME 填入 USER_NAME
 * @param data 传递的数据
 */
export function set_action(name:string,method:string,data:any) {
    let a = ['A', name.toUpperCase(), method.toUpperCase()].join('_');
    if (!Store._actions[a]) {
        throw new Error('Action Not Found:' + a)
        return;
    }
    return Store.dispatch(a, data)
}

/**
 * 排除这些属性和方法
 */
export var exclude = [
    '__defineGetter__',
    '__defineSetter__',
    'hasOwnProperty',
    '__lookupGetter__',
    '__lookupSetter__',
    'isPrototypeOf',
    'propertyIsEnumerable',
    'toString',
    'valueOf',
    '__proto__',
    'toLocaleString',
    'constructor'
]
/**vuex类装饰器 */
export default function Vuex(): any {
    return function name(store: any) {
        return vuexFactory(store)
    }
}
function vuexFactory(store: any) {
    var sclass = new store()
    let name: string = sclass.ClassName || sclass.constructor.name;
    // 初始化容器
    let s: any = {
        state: {},
        getters: {},
        actions: {},
        mutations: {}
    }
    // 获得state变量名
    Object.keys(sclass).forEach((k) => {
        if (k.substr(0, 2) !== '__')
            s.state[k] = sclass[k]
    })
    /**获取原型名称 */
    let methods = [...Object.getOwnPropertyNames(store.prototype)]

    methods.forEach((k: any) => {
        if (/^([AGM])_([A-Z_\d]{1,})$/.test(k)) {
            let ks = k.replace(/^([AGM])_/, '$1_' + name.toUpperCase() + '_')
            switch (k.substr(0, 2)) {
                case 'G_':
                    s.getters[ks] = function (state: any) {
                        return sclass[k].apply(this, arguments)
                    }
                    break;
                case 'A_':
                    s.actions[ks] = function (state: any, data: any) {
                        return sclass[k].apply(this, arguments)
                    }
                    break;
                case 'M_':
                    s.mutations[ks] = function (state: any, data: any) {
                        return sclass[k].apply(this, arguments)
                    }
                    break;
            }
        } else {
            if (!exclude.includes(k))
                console.error('Vuex方法名称不符合规范:' + name + '.' + k)
        }
    })
    return s
}